package club.pinea.session;

import club.pinea.exception.ServiceException;
import club.pinea.model.User;
import club.pinea.send.MessageSend;
import club.pinea.utils.RedisCache;
import club.pinea.utils.SpringContextUtils;
import com.google.protobuf.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static club.pinea.constants.RedisPrefix.TOKEN_PREFIX;
import static club.pinea.constants.RedisPrefix.USER_INFO_PREFIX;

public class GlobalServerPlayerContainer {

    protected static Logger log = LoggerFactory.getLogger(GlobalServerPlayerContainer.class);
    private static ConcurrentHashMap<Integer, Integer> sessionUserIdMap = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Integer, ServerPlayer> serverPlayerMap = new ConcurrentHashMap<>();

    // 登陆  登出  掉线
    public static ServerPlayer playerLogin(IOSession session, Integer uid, String token) {
        RedisCache redisCache = SpringContextUtils.getBean(RedisCache.class);
        String rToken = redisCache.getCacheObject(TOKEN_PREFIX + uid);
        // 判断登录信息是否正确
        if (Objects.equals(token, rToken)) {
            User user = redisCache.getCacheObject(USER_INFO_PREFIX + uid);
            ServerPlayer oldPlayer = serverPlayerMap.get(uid);
            // 正常登录
            if (oldPlayer == null) {
                ServerPlayer player = new ServerPlayer();
                player.updateSession(session);
                player.updatePersonInfo(user, token);
                player.onLogin();
                sessionUserIdMap.put(session.getSessionId(), uid);
                serverPlayerMap.put(uid, player);
                log.info(String.format("玩家[%d] 登陆 Session[%d] IP[%s]", player.getUserId(), session.getSessionId(), player.getMUserIP()));
                return player;
            }
            IOSession oldSession = oldPlayer.getSession();

            // session不为空，说明此前有登录过，或有挤号行为，踢出之前登录的账号
            if (oldSession != null) {
                RemoveSession(oldSession.getSessionId(), "delete old session");
                oldSession.disConnect();
            }
            // 更新新的session连接
            sessionUserIdMap.put(session.getSessionId(), uid);
            oldPlayer.updatePersonInfo(user, token);
            oldPlayer.updateSession(session);
            oldPlayer.onLogin();
            serverPlayerMap.put(uid, oldPlayer);
            log.info(String.format("玩家[%d] 登陆 Session[%d] IP[%s]", oldPlayer.getUserId(), session.getSessionId(), oldPlayer.getMUserIP()));
            return oldPlayer;
        } else {
            // 移出数据
            RemoveSession(session.getSessionId(), "token is not match");
            Integer userId = sessionUserIdMap.remove(session.getSessionId());
            if (userId != null) {
                serverPlayerMap.remove(userId);
            }
            throw new ServiceException("token is not match");
        }
    }


    /**
     * 获取 serverPlayer
     *
     * @param session
     * @return
     */
    public static ServerPlayer getServerPlayer(IOSession session) {
        Integer uid = sessionUserIdMap.get(session.getSessionId());
        if (uid != null) {
            ServerPlayer sp = serverPlayerMap.get(uid);
            if (sp != null) {
                return sp;
            } else {
                RemoveSession(session.getSessionId(), "getServerPlayer");
                log.info(String.format("session[%d] 没有对应的在线用户player，断开连接", session.getSessionId()));
            }
        } else {
            log.info(String.format("session[%d] 没有对应的在线用户id对应，断开连接", session.getSessionId()));
        }
        session.disConnect();
        return null;
    }

    /**
     * 用户退出
     *
     * @param session
     */
    public static void playerLogout(IOSession session) {
        Integer uid = sessionUserIdMap.get(session.getSessionId());
        if (uid != null) {
            ServerPlayer sp = serverPlayerMap.get(uid);
            if (sp != null) {
                log.info(String.format("玩家[%d] 退出 Session[%d] IP[%s]", sp.getUserId(), session.getSessionId(), sp.getMUserIP()));
                // 登出成功
                RemoveServerPlayer(uid);
                RemoveSession(session.getSessionId(), "playerLogout1");
                session.disConnect();
            }
        }
    }


    // 没有关联的掉线用户删除存储
    public static ServerPlayer RemoveServerPlayer(int uid) {
        ServerPlayer sp = serverPlayerMap.remove(uid);
        if (sp != null) {
            log.info("#-#-#-# 移除用户:" + uid + " ServerPlayer.size=" + serverPlayerMap.size());
        }
        return sp;
    }

    public static Integer RemoveSession(int sessionId, String des) {
        Integer uid = sessionUserIdMap.remove(sessionId);
        GlobalSessionContainer.delIOSession(sessionId);
        if (uid != null) {
            log.info("#-#-#-# 移除用户:" + uid + " sessionId=" + sessionId + " at:" + des);
        }
        return uid;
    }


//    public static void sendNotice(ServerPlayer sp) {
//        if (sp != null) {
//            Map<String, String> notice = RedisUtil.getJedis().hgetAll(CacheEnum.GAME_PROCLAMATION_RECORD.getMsg());
//            if (notice != null) {
//                Room.RoomNoticeNotify.Builder notify = Room.RoomNoticeNotify.newBuilder();
//                Date curDt = new Date();
//                for (Map.Entry<String, String> entry : notice.entrySet()) {
//                    try {
//                        if (isNoticeTimeOut(entry.getValue(), curDt)) {
//                            RedisUtil.getJedis().hdel(CacheEnum.GAME_PROCLAMATION_RECORD.getMsg(), entry.getKey());
//                        } else {
//                            Room.RoomNoticeNotify.RoomNotice.Builder n = Room.RoomNoticeNotify.RoomNotice.newBuilder();
//                            n.setId(Integer.valueOf(entry.getKey()));
//                            n.setMsg(entry.getValue());
//                            n.setType(Room.RoomNoticeNotify.RoomNoticeOperType.RoomNoticeOperTypeAdd_VALUE);
//                            notify.addNotices(n);
//                        }
//                    } catch (NumberFormatException ex) {
//                        log.warn("2-notice id:" + entry.getKey() + " error: need int");
//                    }
//                }
//                sp.send(notify.build());
//            }
//        }
//    }

//    private static boolean isNoticeTimeOut(String notice, Date curDt) {
//        try {
//            JSONObject jo = JSONObject.parseObject(notice);
//            if (jo != null) {
//                Date dt = jo.getDate("endtime");
//                if (dt.getTime() < curDt.getTime()) {
//                    return true;
//                }
//            }
//        } catch (Exception ex) {
//            return false;
//        }
//        return false;
//    }

    /**
     * 发送消息给用户
     *
     * @param uid
     * @param msg
     */
    public static void sendMessageToPlayer(int uid, Message msg) {
        if (msg != null) {
            ServerPlayer sp = serverPlayerMap.get(uid);
            if (sp != null) {
                MessageSend.sendToUser(msg, sp.getSession());
            }
        }
    }


    /**
     * 功能描述：发送全服广播
     *
     * @param type     1 全服 2 大厅 3 游戏内
     * @param order    高99-0低
     * @param jump     是否跳转 1可以0不可以
     * @param jumpTo   1 商城 2 游戏内
     * @param gameId   游戏id
     * @param stopTime 停留时间
     * @param speed    播放速度
     * @param content  广播内容
     * @return void
     * 2018年5月3日 下午2:45:31
     */
    public static void sendAllServerBroadCast(int type, int order, int jump, int jumpTo, int gameId, int stopTime, int speed, String content) {
//        NetServerMessageFacotry factory = MyApplicationContextUtil.getBean(NetServerMessageFacotry.class);
//        com.decibel.game.util.MessageSend.sendToGameServerMessage(factory.createBroadCast(type, order, jump, jumpTo, gameId, stopTime, speed, content));
    }

}
